package com.zxy.ziems.server.statistics.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zxy.btp.common.exception.ConditionException;
import com.zxy.btp.mybatis.base.BaseEntity;
import com.zxy.ziems.server.classify.pojo.entity.Classify;
import com.zxy.ziems.server.classify.pojo.entity.ClassifyDeviceProperty;
import com.zxy.ziems.server.classify.service.ClassifyDevicePropertyService;
import com.zxy.ziems.server.classify.service.ClassifyService;
import com.zxy.ziems.server.constant.enums.CalculateTypeEnum;
import com.zxy.ziems.server.domain.DictItem;
import com.zxy.ziems.server.dto.DataQueryDto;
import com.zxy.ziems.server.dto.DateDto;
import com.zxy.ziems.server.dto.DeviceMeasureDateGroupDto;
import com.zxy.ziems.server.energy.enums.EnergyDataTypeEnum;
import com.zxy.ziems.server.energy.pojo.dto.DeviceMeasureDateDTO;
import com.zxy.ziems.server.energy.service.DeviceMeasureDataService;
import com.zxy.ziems.server.service.DictItemService;
import com.zxy.ziems.server.statistics.service.GeneralExportService;
import com.zxy.ziems.server.utils.AssertUtil;
import com.zxy.ziems.server.utils.DateUtils;
import com.zxy.ziems.server.vo.ChartVo;
import com.zxy.ziems.server.vo.ChartYAxisVo;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.OutputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static com.zxy.ziems.server.utils.DateUtils.YMD_PATTERN;

@Service
public class GeneralExportServiceImpl implements GeneralExportService {

    @Autowired
    private ClassifyDevicePropertyService classifyDevicePropertyService;
    @Autowired
    private DictItemService dictItemService;
    @Autowired
    private ClassifyService classifyService;
    @Autowired
    private DeviceMeasureDataService deviceMeasureDataService;

    private static void extractedCharVo(Sheet sheet, List<Map<String, Object>> dataList, CellStyle head, CellStyle content) {

        if (dataList != null && !dataList.isEmpty()) {
            int rowNum = 0;

            // 创建表头
            Row headerRow = sheet.createRow(rowNum++);
            if (!dataList.isEmpty()) {
                int colNum = 0;
                for (String key : dataList.get(0).keySet()) {
                    Cell cell = headerRow.createCell(colNum++);
                    cell.setCellStyle(head);
                    cell.setCellValue(key);
                }
            }

            // 写入数据
            for (Map<String, Object> data : dataList) {
                Row row = sheet.createRow(rowNum++);
                int colNum = 0;
                for (Object value : data.values()) {
                    Cell cell = row.createCell(colNum++);
                    cell.setCellStyle(content);
                    cell.setCellValue(value != null ? value.toString() : "");
                }
            }

        }
    }

    private static ChartYAxisVo buildEmptyChartYAxisVo(Integer size, Classify classify, String type) {
        ChartYAxisVo chartYAxisVo = new ChartYAxisVo();
        chartYAxisVo.setName(classify.getClassifyName());

        chartYAxisVo.setStack(classify.getClassifyId());
        List<BigDecimal> emptyDataList = new ArrayList<>();
        for (int i = 0; i < size; i++) {
            emptyDataList.add(BigDecimal.ZERO);
        }
        chartYAxisVo.setData(emptyDataList);
        return chartYAxisVo;
    }

    private static void setYVal(Map<String, List<DeviceMeasureDateDTO>> thisMap, List<BigDecimal> thisYValueList, String dateTimeStr, Integer type) {
        if (thisMap.containsKey(dateTimeStr)) {
            List<DeviceMeasureDateDTO> pointDataListByDate = thisMap.get(dateTimeStr);
            BigDecimal data = BigDecimal.ZERO;
            if (type == null || type.equals(EnergyDataTypeEnum.ENERGY.getCode())) {
                data = pointDataListByDate.stream().map(DeviceMeasureDateDTO::getStatistic).reduce(BigDecimal.ZERO, BigDecimal::add);
            } else if (type.equals(EnergyDataTypeEnum.CODE.getCode())) {
                data = pointDataListByDate.stream().map(v -> v.getCost() == null ? BigDecimal.ZERO : v.getCost()).reduce(BigDecimal.ZERO, BigDecimal::add);
            }
            thisYValueList.add(data.setScale(2, RoundingMode.HALF_UP));
        } else {
            thisYValueList.add(BigDecimal.ZERO);
        }
    }

    public CellStyle titleStyleExcel(Workbook wb) {
        CellStyle style = wb.createCellStyle();
        Font font = wb.createFont();
        font.setColor(IndexedColors.BLACK.getIndex());
        font.setFontHeightInPoints((short) 15);
        font.setFontName("宋体");
        style.setFont(font);
        style.setAlignment(HorizontalAlignment.CENTER);// 设置水平居中
        style.setVerticalAlignment(VerticalAlignment.CENTER);//设置垂直居中
        style.setWrapText(true);  // 换行
        // 设置边框样式
        style.setBorderTop(BorderStyle.THIN); // 上边框
        style.setBorderBottom(BorderStyle.THIN); // 下边框
        style.setBorderLeft(BorderStyle.THIN); // 左边框
        style.setBorderRight(BorderStyle.THIN); // 右边框

        // 设置边框颜色
        style.setTopBorderColor(IndexedColors.BLACK.getIndex()); // 上边框颜色
        style.setBottomBorderColor(IndexedColors.BLACK.getIndex()); // 下边框颜色
        style.setLeftBorderColor(IndexedColors.BLACK.getIndex()); // 左边框颜色
        style.setRightBorderColor(IndexedColors.BLACK.getIndex()); // 右边框颜色
        return style;
    }

    public Font getFont(Workbook wb) {
        Font font = wb.createFont();
        font.setColor(IndexedColors.BLACK.getIndex());
        font.setFontHeightInPoints((short) 12);
        font.setFontName("宋体");
        return font;
    }

    public CellStyle styleExcel(Workbook wb) {
        CellStyle style = wb.createCellStyle();
        Font font = getFont(wb);
        style.setFont(font);
        style.setAlignment(HorizontalAlignment.CENTER);// 设置水平居中
        style.setVerticalAlignment(VerticalAlignment.CENTER);//设置垂直居中
        style.setWrapText(true);  // 换行
        // 设置边框样式
        style.setBorderTop(BorderStyle.THIN); // 上边框
        style.setBorderBottom(BorderStyle.THIN); // 下边框
        style.setBorderLeft(BorderStyle.THIN); // 左边框
        style.setBorderRight(BorderStyle.THIN); // 右边框

        // 设置边框颜色
        style.setTopBorderColor(IndexedColors.BLACK.getIndex()); // 上边框颜色
        style.setBottomBorderColor(IndexedColors.BLACK.getIndex()); // 下边框颜色
        style.setLeftBorderColor(IndexedColors.BLACK.getIndex()); // 左边框颜色
        style.setRightBorderColor(IndexedColors.BLACK.getIndex()); // 右边框颜色
        return style;
    }

    public List<Map<String, Object>> dataConvert(String l, ChartVo chartVo) {
        List<Map<String, Object>> dataList = new ArrayList<>();

        List<String> xAxisList = chartVo.getXAxisList();
        List<ChartYAxisVo> yAxisList = chartVo.getYAxisList();
        for (int i = 0; i < yAxisList.size(); i++) {
            Map<String, Object> data = new LinkedHashMap<>();
            data.put(l, yAxisList.get(i).getName());
            List<BigDecimal> yd = yAxisList.get(i).getData();
            for (int j = 0; j < yd.size(); j++) {
                data.put(xAxisList.get(j), yd.get(j));
            }
            dataList.add(data);
        }
        return dataList;

    }

    @Override
    public void export(HttpServletResponse response, DataQueryDto dataQueryDto) {
        // 设置 HTTP 响应头
        String fileName = dataQueryDto.getItemName();
        String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8).replaceAll("\\+", "%20");
        response.setContentType("application/octet-stream");
        response.setHeader("Content-disposition", "attachment;filename=" + encodedFileName + ".xlsx");
        response.setCharacterEncoding("utf-8");

        Workbook workbook = new XSSFWorkbook();

        Map<String, ChartVo> dataChart = getDataChart(dataQueryDto);

        dataChart.keySet().forEach(l -> {

            Sheet sheet = workbook.createSheet(l);

            List<Map<String, Object>> dataList = dataConvert(l, dataChart.get(l));

            extractedCharVo(sheet, dataList, titleStyleExcel(workbook), styleExcel(workbook));

        });

        try {
            OutputStream out = response.getOutputStream();
            workbook.write(out);
            out.flush();
            out.close();
        } catch (Exception e) {
            throw new ConditionException(e.getMessage());
        }

    }

    private String getclassifyId(String dictCode, String itemName) {
        String classifyId = null;
        // 获取字典配置分类项
        List<DictItem> dictItems = dictItemService.getByDictCode(dictCode);
        if (dictItems.isEmpty()) {
            classifyId = null;
        } else {
            DictItem dictItem = dictItems.stream().filter(m -> m.getItemName().equals(itemName)).findFirst().orElse(new DictItem());
            classifyId = dictItem.getItemCode();
        }
        AssertUtil.nonNull(classifyId, "未找到字典配置");
        return classifyId;
    }

    private Map<String, ChartVo> getDataChart(DataQueryDto dataQueryDto) {
        //根据查询条件计算起止时间
        String queryType = dataQueryDto.getQueryType();
        DateDto dateDto = DateUtils.dateQueryConvert(queryType, dataQueryDto.getStartDay(), dataQueryDto.getEndDay(), false);
        //构建x轴
        List<LocalDateTime> list = DateUtils.dateToList(queryType, dateDto.getStartDay(), dateDto.getEndDay());

        List<DictItem> byDictCode = dictItemService.getByDictCode(dataQueryDto.getDictCode());

        List<String> queryIdAllList = new ArrayList<>();
        Map<String, ChartVo> chartVoMap = new HashMap<>();

        Map<String, List<String>> classifyNameMapClassifyIds = new HashMap<>();
        Map<String, List<String>> classifyIdMapClassifyIds = new HashMap<>();

        byDictCode.forEach(l -> {
            String classifyId = getclassifyId(dataQueryDto.getDictCode(), l.getItemName());
            // 根据分类ID获取下属的分类
            List<String> classifyIds = classifyService.getChildrenId(classifyId);
            if (classifyIds == null || classifyIds.isEmpty()) {
                classifyIds.add(classifyId);
            }

            queryIdAllList.addAll(classifyIds);

            ChartVo chartVo = new ChartVo();
            chartVo.setXAxisList(DateUtils.xAxisConvert(queryType, list));

            chartVoMap.put(l.getItemName(), chartVo);
            classifyNameMapClassifyIds.put(l.getItemName(), classifyIds);
            classifyIdMapClassifyIds.put(classifyId, classifyIds);

        });

        List<ClassifyDeviceProperty> devicePropertyAllList = new ArrayList<>();
        if (queryIdAllList != null && !queryIdAllList.isEmpty()) {
            devicePropertyAllList = getClassifyDeviceProperties(queryIdAllList);
        }

        Map<String, List<ClassifyDeviceProperty>> devicePropertyMap = devicePropertyAllList.stream()
                .collect(Collectors.groupingBy((px) -> px.getClassifyId()));

        Map<String, Map<String, List<ClassifyDeviceProperty>>> classifyIdMapChildMapDevice = new HashMap<>();

        classifyIdMapClassifyIds.keySet().forEach(cl -> {
            List<String> classifyIds = classifyIdMapClassifyIds.get(cl);
            Map<String, List<ClassifyDeviceProperty>> el = new HashMap<>();
            classifyIds.forEach(d -> el.put(d, devicePropertyMap.get(d)));

            classifyIdMapChildMapDevice.put(cl, el);
        });

        Map<String, List<DeviceMeasureDateDTO>> dateGroupDtos = getDeviceMeasureDateTypeGroupDtosCombine(queryType, dateDto.getStartDay(), dateDto.getEndDay(),
                classifyIdMapChildMapDevice);

        classifyNameMapClassifyIds.keySet().stream().forEach(l -> {
            ChartVo chartVo = chartVoMap.get(l);
            List<String> queryIdList = classifyNameMapClassifyIds.get(l);

            List<ChartYAxisVo> chartYList = new ArrayList<>();

            for (String classifyId : queryIdList) {
                Classify classify = classifyService.getById(classifyId);
                if (classify == null) {
                    continue;
                }

                List<ClassifyDeviceProperty> devicePropertyList = devicePropertyMap.get(classifyId);

                //判断是否需要返回空值
                if (CollectionUtil.isEmpty(devicePropertyList)) {
                    chartYList.add(buildEmptyChartYAxisVo(list.size(), classify, "bar"));
                    continue;
                }

                List<DeviceMeasureDateDTO> dateDtos = dateGroupDtos.get(classifyId);

                //根据点位数据时间进行分组汇总数据
                if (CollectionUtil.isEmpty(dateDtos)) {
                    chartYList.add(buildEmptyChartYAxisVo(list.size(), classify, "bar"));
                    continue;
                }

//            multipleProcess(dateDtos, classifyDeviceProperty.getMultiple());

                //按照查询类型和数据类型对数据时间进行处理，并分组，将数据处理为x轴需要的格式进行匹配
                Map<String, List<DeviceMeasureDateDTO>> thisMap = buildDataByDataType(dateDtos);
                List<BigDecimal> yValueList = new ArrayList<>();
                for (String dateTimeStr : chartVo.getXAxisList()) {
                    //本周期数据
                    setYVal(thisMap, yValueList, dateTimeStr, dataQueryDto.getDataType());
                }
                // 过滤，电量10以下的展示为0，yValueList中小于10的赋值0
                if (classify.getEnergyType().equals("电")) {
                    for (int i = 0; i < yValueList.size(); i++) {
                        BigDecimal value = yValueList.get(i);
                        if (value != null && value.compareTo(new BigDecimal(10)) < 0) {
                            yValueList.set(i, new BigDecimal(0));
                        }
                    }
                }
                ChartYAxisVo chartYAxisVo = new ChartYAxisVo();
                chartYAxisVo.setName(classify.getClassifyName());
                chartYAxisVo.setData(yValueList);

                chartYAxisVo.setStack(classifyId);
                chartYList.add(chartYAxisVo);
            }
            chartVo.setYAxisList(chartYList);

        });

        return chartVoMap;
    }

    /**
     * 根据分类ID获取设备分类属性关系集
     *
     * @param classifyIdList
     * @return
     */
    private List<ClassifyDeviceProperty> getClassifyDeviceProperties(List<String> classifyIdList) {
        QueryWrapper<ClassifyDeviceProperty> queryClass = new QueryWrapper<>();
        queryClass.lambda().in(ClassifyDeviceProperty::getClassifyId, classifyIdList)
                .eq(BaseEntity::getDeleteStatus, 0);
        List<ClassifyDeviceProperty> devicePropertyList = classifyDevicePropertyService.list(queryClass);
        return devicePropertyList;
    }

    private Map<String, List<DeviceMeasureDateDTO>> buildDataByDataType(List<DeviceMeasureDateDTO> pointDataList) {
        //如果查询的不是日数据，且是自动的点位，需要把数据时间转换为天进行分组
        Map<String, List<DeviceMeasureDateDTO>> map = new HashMap<>();
        if (CollectionUtil.isEmpty(pointDataList)) {
            return map;
        }
        for (DeviceMeasureDateDTO pointData : pointDataList) {
            String dateStr = pointData.getDayStr();
            if (map.containsKey(dateStr)) {
                List<DeviceMeasureDateDTO> dataList = map.get(dateStr);
                dataList.add(pointData);
            } else {
                List<DeviceMeasureDateDTO> newList = new ArrayList<>();
                newList.add(pointData);
                map.put(dateStr, newList);
            }
        }
        return map;
    }

    private Map<String, List<DeviceMeasureDateDTO>> getDeviceMeasureDateTypeGroupDtosCombine(String queryType, String startDay, String endDay, Map<String, Map<String, List<ClassifyDeviceProperty>>> classifyIdMapChildMapDevice) {
        Map<String, List<DeviceMeasureDateDTO>> resultMap = new HashMap<>();

        Map<String, List<ClassifyDeviceProperty>> devicePropertyMap = new HashMap<>();

        classifyIdMapChildMapDevice.keySet().forEach(l -> {
            List<ClassifyDeviceProperty> classifyDevicePropertyList = new ArrayList<>();
            Map<String, List<ClassifyDeviceProperty>> stringListMap = classifyIdMapChildMapDevice.get(l);
            for (String d : stringListMap.keySet()) {
                List<ClassifyDeviceProperty> cd = stringListMap.get(d);
                if (cd != null && !cd.isEmpty()) {
                    classifyDevicePropertyList.addAll(cd);
                }

            }
            devicePropertyMap.put(l, classifyDevicePropertyList);

        });

        devicePropertyMap.keySet().forEach(classifyId -> {
            List<ClassifyDeviceProperty> devicePropertyList = devicePropertyMap.get(classifyId);

            if (CollectionUtil.isNotEmpty(devicePropertyList)) {

                Classify classify = classifyService.getById(classifyId);

                Set<String> deviceIdSet = devicePropertyList.stream().map(ClassifyDeviceProperty::getDeviceId).collect(Collectors.toSet());
                ClassifyDeviceProperty classifyDeviceProperty = devicePropertyList.get(0);
                // 设备参数ID
                String dataTypeId = classifyDeviceProperty.getDataTypeId();
                // 计算方式 1.实时值，2.增量值 3.辅助计算值
                Integer calculateType = classifyDeviceProperty.getCalculateType();

                List<DeviceMeasureDateDTO> dateDtos = new ArrayList<>();

                if (calculateType.equals(CalculateTypeEnum.MEASURE.getCode())) {
                    // 如果是平均，获取平均的统计
                    Map<String, List<DeviceMeasureDateDTO>> avgResult = avgTree(classify.getClassifyId(), classifyIdMapChildMapDevice.get(classifyId), queryType, DateUtils.checkFormat(startDay, YMD_PATTERN),
                            DateUtils.checkFormat(endDay, YMD_PATTERN), deviceIdSet, dataTypeId);
                    resultMap.putAll(avgResult);
                } else if (calculateType.equals(CalculateTypeEnum.INCREMENT.getCode())) {
                    // 如果是求和，获取求和统计
                    Map<String, List<DeviceMeasureDateDTO>> sumResult = sumTree(classify.getClassifyId(), classifyIdMapChildMapDevice.get(classifyId), queryType, DateUtils.checkFormat(startDay, YMD_PATTERN),
                            DateUtils.checkFormat(endDay, YMD_PATTERN), deviceIdSet, dataTypeId);
                    resultMap.putAll(sumResult);
                } else if (calculateType.equals(CalculateTypeEnum.MEASURE_INCREMENT.getCode())) {
                    // 如果是实时增量值（采集值是按小时统计的值），天统计则会使用实际值求和
                    Map<String, List<DeviceMeasureDateDTO>> sumRealResult = sumTreeReal(classify.getClassifyId(), classifyIdMapChildMapDevice.get(classifyId), queryType, DateUtils.checkFormat(startDay, YMD_PATTERN),
                            DateUtils.checkFormat(endDay, YMD_PATTERN), deviceIdSet, dataTypeId);
                    resultMap.putAll(sumRealResult);
                }

                resultMap.put(classifyId, dateDtos);
            }


        });

        return resultMap;
    }

    public Map<String, List<DeviceMeasureDateDTO>> sumTree(String classifyId, Map<String, List<ClassifyDeviceProperty>> childClassifyIdDevice, String dateType, LocalDate start, LocalDate end, Set<String> deviceIds, String dataTypeId) {
        // 获取分类信息
        List<Classify> classifyList = classifyService.classifyListByClassifyId(classifyId);

        List<String> classifyIds = classifyList.stream().map(Classify::getClassifyId).collect(Collectors.toList());

        // 获取所有设备结果
        List<DeviceMeasureDateGroupDto> deviceMeasureDateDtoList = deviceMeasureDataService.getDeviceSum(dateType, start, end, deviceIds, dataTypeId, classifyIds);

        Map<String, List<DeviceMeasureDateGroupDto>> resultGroupMap = new HashMap<>();

        childClassifyIdDevice.keySet().forEach(l -> {
            List<ClassifyDeviceProperty> classifyDevicePropertyList = childClassifyIdDevice.get(l);
            if (classifyDevicePropertyList != null) {
                List<String> deviceIdCollect = classifyDevicePropertyList.stream().map(ClassifyDeviceProperty::getDeviceId).toList();
                List<DeviceMeasureDateGroupDto> deviceMeasureDateGroupDtos = deviceMeasureDateDtoList.stream().filter(d -> deviceIdCollect.contains(d.getDeviceId())).toList();

                resultGroupMap.put(l, deviceMeasureDateGroupDtos);
            }


        });

        Map<String, List<DeviceMeasureDateDTO>> result = new HashMap<>();

        resultGroupMap.keySet().forEach(k -> {
            // 根据时间分组
            Map<String, List<DeviceMeasureDateGroupDto>> map = resultGroupMap.get(k).stream().collect(Collectors.groupingBy(m -> m.getDayStr()));

            // 各分组求和
            List<DeviceMeasureDateDTO> deviceMeasureDateDTOList1 = extracted(map);

            result.put(k, deviceMeasureDateDTOList1);
        });

        return result;
    }

    private List<DeviceMeasureDateDTO> extracted(Map<String, List<DeviceMeasureDateGroupDto>> map) {
        List<DeviceMeasureDateDTO> dateDtos = new ArrayList<>();
        for (String s : map.keySet()) {
            List<DeviceMeasureDateGroupDto> deviceMeasureDateGroupDtoList = map.get(s);
            BigDecimal bigDecimal = new BigDecimal(0);
            BigDecimal costDecimal = new BigDecimal(0);
            for (DeviceMeasureDateGroupDto deviceMeasureDateGroupDto : deviceMeasureDateGroupDtoList) {
                bigDecimal = bigDecimal.add(deviceMeasureDateGroupDto.getStatistic());
                if (deviceMeasureDateGroupDto.getCost() != null) {
                    costDecimal = costDecimal.add(deviceMeasureDateGroupDto.getCost());
                }
            }
            DeviceMeasureDateDTO deviceMeasureDateDto = new DeviceMeasureDateDTO();
            deviceMeasureDateDto.setDayStr(s);
            deviceMeasureDateDto.setStatistic(bigDecimal);
            deviceMeasureDateDto.setCost(costDecimal);
            dateDtos.add(deviceMeasureDateDto);
        }
        return dateDtos;
    }

    public Map<String, List<DeviceMeasureDateDTO>> avgTree(String classifyId, Map<String, List<ClassifyDeviceProperty>> childClassifyIdDevice, String dateType, LocalDate start, LocalDate end, Set<String> deviceIds, String dataTypeId) {
        // 获取分类信息
        List<Classify> classifyList = classifyService.classifyListByClassifyId(classifyId);

        List<String> classifyIds = classifyList.stream().map(Classify::getClassifyId).collect(Collectors.toList());

        // 获取所有设备结果
        List<DeviceMeasureDateGroupDto> deviceMeasureDateDtoList = deviceMeasureDataService.getDeviceAvg(dateType, start, end, deviceIds, dataTypeId, classifyIds);

        Map<String, List<DeviceMeasureDateGroupDto>> resultGroupMap = new HashMap<>();

        childClassifyIdDevice.keySet().forEach(l -> {
            List<ClassifyDeviceProperty> classifyDevicePropertyList = childClassifyIdDevice.get(l);
            if (classifyDevicePropertyList != null) {
                List<String> deviceIdCollect = classifyDevicePropertyList.stream().map(ClassifyDeviceProperty::getDeviceId).toList();
                List<DeviceMeasureDateGroupDto> deviceMeasureDateGroupDtos = deviceMeasureDateDtoList.stream().filter(d -> deviceIdCollect.contains(d.getDeviceId())).toList();

                resultGroupMap.put(l, deviceMeasureDateGroupDtos);
            }


        });

        Map<String, List<DeviceMeasureDateDTO>> result = new HashMap<>();

        resultGroupMap.keySet().forEach(k -> {
            // 根据时间分组
            Map<String, List<DeviceMeasureDateGroupDto>> map = deviceMeasureDateDtoList.stream().collect(Collectors.groupingBy(m -> m.getDayStr()));

            // 各分组求和
            List<DeviceMeasureDateDTO> deviceMeasureDateDTOList1 = extractedSvg(map);

            result.put(k, deviceMeasureDateDTOList1);
        });

        return result;

    }

    private List<DeviceMeasureDateDTO> extractedSvg(Map<String, List<DeviceMeasureDateGroupDto>> map) {
        List<DeviceMeasureDateDTO> dateDtos = new ArrayList<>();
        for (String s : map.keySet()) {
            List<DeviceMeasureDateGroupDto> deviceMeasureDateGroupDtoList = map.get(s);
            BigDecimal bigDecimal = new BigDecimal(0);
            BigDecimal costDecimal = new BigDecimal(0);
            for (DeviceMeasureDateGroupDto deviceMeasureDateGroupDto : deviceMeasureDateGroupDtoList) {
                bigDecimal = bigDecimal.add(deviceMeasureDateGroupDto.getStatistic());
                if (deviceMeasureDateGroupDto.getCost() != null) {
                    costDecimal = costDecimal.add(deviceMeasureDateGroupDto.getCost());
                }
            }
            DeviceMeasureDateDTO deviceMeasureDateDto = new DeviceMeasureDateDTO();
            deviceMeasureDateDto.setDayStr(s);
            if (deviceMeasureDateGroupDtoList.size() > 0) {
                // 分组下数据求平均
                bigDecimal = bigDecimal.divide(new BigDecimal(deviceMeasureDateGroupDtoList.size()), 2, RoundingMode.HALF_UP);
            }
            deviceMeasureDateDto.setStatistic(bigDecimal);
            deviceMeasureDateDto.setCost(costDecimal);
            dateDtos.add(deviceMeasureDateDto);
        }
        return dateDtos;
    }


    public Map<String, List<DeviceMeasureDateDTO>> sumTreeReal(String classifyId, Map<String, List<ClassifyDeviceProperty>> childClassifyIdDevice, String dateType, LocalDate start, LocalDate end, Set<String> deviceIds, String dataTypeId) {
        // 获取分类信息
        List<Classify> classifyList = classifyService.classifyListByClassifyId(classifyId);

        List<String> classifyIds = classifyList.stream().map(Classify::getClassifyId).collect(Collectors.toList());

        // 获取所有设备结果
        List<DeviceMeasureDateGroupDto> deviceMeasureDateDtoList = deviceMeasureDataService.getDeviceRealSum(dateType, start, end, deviceIds, dataTypeId, classifyIds);


        Map<String, List<DeviceMeasureDateGroupDto>> resultGroupMap = new HashMap<>();

        childClassifyIdDevice.keySet().forEach(l -> {
            List<ClassifyDeviceProperty> classifyDevicePropertyList = childClassifyIdDevice.get(l);
            if (classifyDevicePropertyList != null) {
                List<String> deviceIdCollect = classifyDevicePropertyList.stream().map(ClassifyDeviceProperty::getDeviceId).toList();
                List<DeviceMeasureDateGroupDto> deviceMeasureDateGroupDtos = deviceMeasureDateDtoList.stream().filter(d -> deviceIdCollect.contains(d.getDeviceId())).toList();

                resultGroupMap.put(l, deviceMeasureDateGroupDtos);
            }
        });

        Map<String, List<DeviceMeasureDateDTO>> result = new HashMap<>();

        resultGroupMap.keySet().forEach(k -> {
            // 根据时间分组
            Map<String, List<DeviceMeasureDateGroupDto>> map = deviceMeasureDateDtoList.stream().collect(Collectors.groupingBy(m -> m.getDayStr()));

            // 各分组求和
            List<DeviceMeasureDateDTO> deviceMeasureDateDTOList1 = extracted(map);

            result.put(k, deviceMeasureDateDTOList1);
        });

        return result;

    }

}
